package com.tanhua.dubbo.huanxin.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import com.tanhua.dubbo.api.HuanXinApi;
import com.tanhua.dubbo.huanxin.exception.UnauthorizedException;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class RequestService {

    @DubboReference(version = "1.0.0")
    private HuanXinApi huanXinApi;

    @Autowired
    private TokenService tokenService;

    /**
     * 通用的环信请求方法
     * @param url 请求地址
     * @param body 请求体参数
     * @param method 请求方式
     * @return 响应
     */
    @Retryable(value = RuntimeException.class,
            maxAttempts = 3,
            backoff = @Backoff(delay = 2000L, multiplier = 2))
    public HttpResponse execute(String url, String body, Method method) {

        HttpRequest httpRequest;

        switch (method) {
            case GET:
                httpRequest = HttpRequest.get(url);
                break;
            case POST:
                httpRequest = HttpRequest.post(url);
                break;
            case PUT:
                httpRequest = HttpRequest.put(url);
                break;
            case DELETE:
                httpRequest = HttpRequest.delete(url);
                break;
            default:
                return null;

        }

        HttpResponse response = httpRequest.timeout(10000)
                .header("Content-Type", "application/json")
                .header("Authorization", StrUtil.format("Bearer {}", huanXinApi.getToken()))
                .body(body)
                .execute();

        if(response.getStatus() == 401) {
            //token过期了，重新刷新
            this.tokenService.refreshToken();
            //抛出异常，进行方法重试
            throw new UnauthorizedException(url, body, method);
        }

        return response;
    }

    @Recover //全部重试失败后执行
    public HttpResponse recover(UnauthorizedException e) {
        //TODO 发送短信 或 邮件通知相关负责人
        log.error("获取token失败！url = " + e.getUrl() + ", body = " + e.getBody() + ", method = " + e.getMethod().toString());
        //如果重试5次后，依然不能获取到token，说明网络或账号出现了问题，只能返回null了，后续的请求将无法再执行
        return null; //返回默认
    }
}
